package tech.hdis.framework.restful;

import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.Map;

/**
 * 自定义Restful工具
 *
 * @author 黄志文
 */
@Slf4j
@Configuration
public class Restful {

    private static OkHttpClient okHttpClient;

    @Autowired
    public void setOkHttpClient(OkHttpClient okHttpClient) {
        Restful.okHttpClient = okHttpClient;
    }

    @Bean
    public OkHttpClient okHttpClient() {
        OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
        return clientBuilder.build();
    }

    /**
     * FormBody
     *
     * @param formBody FormBody
     */
    public static FormBody formBody(Map<String, String> formBody) {
        FormBody.Builder formEncodingBuilder = new FormBody.Builder();
        for (Map.Entry<String, String> entry : formBody.entrySet()) {
            formEncodingBuilder.add(entry.getKey(), entry.getValue());
        }
        return formEncodingBuilder.build();
    }

    /**
     * JsonBody
     *
     * @param jsonBody jsonBody
     */
    private static RequestBody jsonBody(Object jsonBody) {
        MediaType mediaType = MediaType.get("application/json;charset=UTF-8");
        return RequestBody.create(mediaType, JSONUtils.toJson(jsonBody));
    }


    /**
     * POST，消息体为Json，返回值为Json
     *
     * @param url          url
     * @param body         请求数据
     * @param responseType 返回值类型
     * @param params       URL部分请求参数
     * @param <T>          返回值类型
     * @return Object
     */
    public static <T> T postForObject(String url, Object body, Class<T> responseType, Object... params) {
        String fullUrl = String.format(url, params);
        log.debug("Post url：{}", String.format(url, params));
        RequestBody requestBody = null;
        if (body instanceof FormBody) {
            requestBody = (FormBody) body;
        } else {
            requestBody = jsonBody(body);
            log.debug("Post body：{}", JSONUtils.toJson(body));
        }
        Request.Builder builder = new Request.Builder();
        Request request = builder.post(requestBody).url(fullUrl).build();
        Call call = okHttpClient.newCall(request);
        Response response;
        String responseBody;
        try {
            response = call.execute();
            responseBody = response.body().string();
        } catch (IOException e) {
            throw new RestfulException(fullUrl, e);
        }
        if (!response.isSuccessful()) {
            throw new RestfulException(url);
        }
        if (responseType.equals(String.class)) {
            return (T) responseBody;
        }
        if (StringUtils.isEmpty(responseBody)) {
            return null;
        }
        return JSONUtils.fromJson(responseBody, responseType);
    }

    /**
     * GET，返回值为Json
     *
     * @param url          url
     * @param responseType 返回值类型
     * @param params       URL部分请求参数
     * @param <T>          返回值类型
     * @return Object
     */
    public static <T> T getForObject(String url, Class<T> responseType, Object... params) {
        String fullUrl = String.format(url, params);
        log.debug("Get Url：{}", fullUrl);
        Request.Builder builder = new Request.Builder();
        Request request = builder.get().url(fullUrl).build();
        Call call = okHttpClient.newCall(request);
        Response response;
        String responseBody;
        try {
            response = call.execute();
            responseBody = response.body().string();
        } catch (IOException e) {
            throw new RestfulException(fullUrl, e);
        }
        if (!response.isSuccessful()) {
            throw new RestfulException(url);
        }
        if (responseType.equals(String.class)) {
            return (T) responseBody;
        }
        if (StringUtils.isEmpty(responseBody)) {
            return null;
        }
        return JSONUtils.fromJson(responseBody, responseType);
    }
}
